package com.wubai.rest;

import com.wubai.basicAuth.BasicAuthAccess;
import com.wubai.basicAuth.HttpManager;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.client.HttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * HttpClient自带的HttpDelete方法是不支持上传body的，所以重写delete方法
 * 采集告警列表如果存在cpu和内存使用率存在告警 生成集群不正常标志文件：mrs_abnormal.ck，
 * 告警记录在：mrs_alarms_all.log
 *
 * 
 * @version [V100R002C30, 2014-09-09]
 * @since [OM 1.0]
 */
public class mrsClusterAlarms {
    private static final Logger LOG = LoggerFactory.getLogger(mrsClusterAlarms.class);
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    /* 查询按时间倒叙，状态是未恢复的告警
     告警类型。取值范围：0：全部（默认）1 : 未恢复告警 2 : 已恢复告警
     告警级别。0：全部（默认）1 : Critical 2 : Major 3 : Minor 4 : Warning*/
    private static final String QUERY_ALARMS_LIST_URL = "/api/v2/alarms?limit=50&offset=0&status=1&order=desc"
            + "&order_by=occurTime";

    /**
     * 程序运行入口
     *
     * @param args 参数
     */
    public static void main(String[] args) {
        LOG.info("Enter main.{}");

        // 文件UserInfo.properties的路径
        String userFilePath = "./conf/UserInfo.properties";
        String logPath = System.getProperty("user.dir") + File.separator + "logs";
//        String YARN_KILL_APP_SHELL = "source /opt/mrsClient/bigdata_env && /usr/bin/python3 "+System.getProperty("user.dir") + File.separator +"yarn_running.py";
//        String YARN_KILL_APP_SHELL = args[0];
        InputStream userInfo = null;
        ResourceBundle resourceBundle = null;
        try {
            File file = new File(userFilePath);
            if (!file.exists()) {
                LOG.error("The user info file doesn't exist.");
                return;
            }
            LOG.info("Get the web info and user info from file {} ", file);

            userInfo = new BufferedInputStream(new FileInputStream(file));
            resourceBundle = new PropertyResourceBundle(userInfo);

            // 获取用户名
            String userName = resourceBundle.getString("userName");
            LOG.info("The user name is : {}.", userName);
            if (userName == null || userName.isEmpty()) {
                LOG.error("The userName is empty.");
            }

            // 获取用户密码
            String password = resourceBundle.getString("password");
            if (password == null || password.isEmpty()) {
                LOG.error("The password is empty.");
            }

            String webUrl = resourceBundle.getString("webUrl");
            LOG.info("The webUrl is : {}.", webUrl);
            if (password == null || password.isEmpty()) {
                LOG.error("The password is empty.");
            }

            // userTLSVersion是必备的参数，是处理jdk1.6服务端连接jdk1.8服务端时的重要参数，如果用户使用的是jdk1.8该参数赋值为空字符串即可
            String userTLSVersion = "";

            // 调用firstAccess接口完成登录认证
            LOG.info("Begin to get httpclient and first access.");
            BasicAuthAccess authAccess = new BasicAuthAccess();
            HttpClient httpClient = authAccess.loginAndAccess(webUrl, userName, password, userTLSVersion);

            LOG.info("Start to access REST API.");

            HttpManager httpManager = new HttpManager();
            String operationName = "";
            String operationUrl = "";

            // 访问大数据集群接口完成查找alarms列表
            operationName = "QueryAlarmsList";
            operationUrl = webUrl + QUERY_ALARMS_LIST_URL;
            String responseLineContent = httpManager.sendHttpGetRequest(httpClient, operationUrl, operationName);
            List<Map> alarmsList = jsonToMaps(responseLineContent);
            LOG.info("未恢复的告警列表：");
            LOG.info("The {} response is {}.", operationName, alarmsList);
            String searchCpuId = args[0]; //传入告警id
            String searchMemoryId = "ALM-12018";
            File dir = new File(logPath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            if (!responseLineContent.contains(searchCpuId) && !responseLineContent.contains(searchMemoryId)) {
                LOG.info("不存在CPU告警或存在内存告警");
                File ck = new File(logPath + File.separator + "mrs_abnormal.ck");
                if (ck.exists()) {
                    LOG.info("不存在CPU告警或存在内存告警 删除标志文件：mrs_abnormal.ck");
                    ck.delete();  //删除ck文件
                }
            } else {
                LOG.info("存在CPU告警或存在内存告警");
                File ck = new File(logPath + File.separator + "mrs_abnormal.ck");
//                 boolean isCreated = ck.createNewFile();
                Date date = new Date();
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                int alarms_num = 0;  // 获取cpu、内存 告警主机数量
                for (int i = 0; i < alarmsList.size(); i++) {
                    String alarm = alarmsList.get(i).toString();
                    LOG.info(alarm);
                    if (alarm.contains(searchCpuId) || alarm.contains(searchMemoryId)) {
                        try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(
                                new FileOutputStream(logPath + File.separator + "mrs_alarms_all.log", true), StandardCharsets.UTF_8))) {
                            pw.println(df.format(date) + " " + alarm);
                            LOG.info("未恢复的告警列表已成功写入到mrs_alarms_all.log文件中");
                            alarms_num++;
                        } catch (IOException e) {
                            LOG.error("写入文件时出现错误：" + e.getMessage());
                        }
                    }
                }
                boolean flag = Boolean.parseBoolean(args[1]);
                if (flag){
                    LOG.info("关联告警主机数量！");
                    LOG.info("存在CPU告警或存在内存告警 告警主机数量：{}", alarms_num);
                    if (alarms_num >= 3) {
                        LOG.info("存在CPU告警或存在内存告警 告警主机数量 大于等于3台");
                        LOG.info("产生标志文件：mrs_abnormal.ck");
                        boolean isCreated = ck.createNewFile();
                    } else if (alarms_num >= 1 && alarms_num < 3) {
                        LOG.info("存在CPU告警或存在内存告警 告警主机数量 小于3台,集群正常可用,不杀业务！");
                        File ck1 = new File(logPath + File.separator + "mrs_abnormal.ck");
                        if (ck1.exists()) {
                            LOG.info("告警主机数量 小于3台 删除标志文件：mrs_abnormal.ck");
                            ck.delete();  //删除ck文件
                        }
                    }
                }else {
                    LOG.info("不关联告警主机数量！");
                    LOG.info("产生标志文件：mrs_abnormal.ck");
                    boolean isCreated = ck.createNewFile();
                }
            }
            File ff = new File(logPath);
            File f = new File(ff, "mrs_alarms_all.log");
            if (f.exists()) {
                long fileSizeInBytes = f.length();
                // 将字节数转换为MB
                long fileSizeInMB = fileSizeInBytes / (1024 * 1024);
                // 判断大于100MB 删除日志文件
                if (fileSizeInMB > 100) {
                    LOG.info("大于100MB删除日志文件：mrs_alarms_all.log");
                    f.delete();
                }
            }
        } catch (FileNotFoundException e) {
            LOG.error("File not found exception.");
        } catch (IOException e) {
            e.printStackTrace();
            LOG.error(e.getMessage());
        } catch (Throwable e) {
            e.printStackTrace();
            LOG.error(e.getMessage());
        } finally {
            if (userInfo != null) {
                try {
                    userInfo.close();
                } catch (IOException e) {
                    LOG.error("IOException.");
                }
            }
        }
    }

    public static List<Map> jsonToMaps(String json) throws IOException {

        Map map = OBJECT_MAPPER.readValue(json, Map.class);
        return (List) (map.get("alarms"));
    }
}
